/**
 * 
 */
package com.li.utils;

import java.io.UnsupportedEncodingException;
import java.security.DigestException;
import java.util.HashMap;
import java.util.Map;


import com.li.user.JsApiSignInfo;
import com.li.user.WxPayInfo;
import com.li.user.WxPayReturnPrePayId;
import com.tencent.common.Configure;

/**
 * 微信支付接口
 * @author liandyao
 * @date 2016-12-19
 * @version 1.0
 */
public class WeixinPayUtil {
	
	public static String requestUrl_pay="https://api.mch.weixin.qq.com/pay/unifiedorder";
 
	/**
	 * 经测试通过的xml文件
	 */
	private static String xml = "<xml>"+
			"<appid>wx60483396471050f8</appid>"+
			"<body>aaaa</body>"+
			"<device_info>w</device_info>"+
			"<mch_id>1415368202</mch_id>"+
			"<nonce_str>T18F11UQGBZD00CF</nonce_str>"+
			"<notify_url>http://lifenyao.vicp.net/weixin/pay_jxth.jsp</notify_url>"+
			"<openid>o2j9nwmZmakpXaUZAI2_pgpEE0E8</openid>"+
			"<out_trade_no>20161221001</out_trade_no>"+
			"<spbill_create_ip>118.206.227.140</spbill_create_ip>"+
			"<total_fee>1</total_fee>"+
			"<trade_type>JSAPI</trade_type>"+
			"<sign>A061F4A057CD59F04CFE24F1C51006DF</sign>"+
		"</xml>";
	
	/**
	 * 微信支付第一步,发送支付信息
	 * @param payInfo
	 * @return
	 * @throws UnsupportedEncodingException 
	 */
	public static String sendPayInfo(WxPayInfo payInfo) throws UnsupportedEncodingException{
		
		String xml = XMLUtil.convertToXml(payInfo);  
		System.out.println("需要发送的xml字符串:::::"+xml);
		String result = WeixinUtil.httpRequestByXml(requestUrl_pay, "POST", xml);
		System.out.println("发送的xml字符串::得到的值:::"+result);
		return result ;
	}
	
	
	
	/**
	 * 第二步.将得到的prePayId再次签名.把这个签名送到页面上
	 * @param prePay
	 * @return
	 */
	private static String getSignByPrePayId(WxPayReturnPrePayId  prePay){
		//这里使用map的原因是微信的签名两次字符串不一样,例如appid,第二次签名是appId,太坑,大坑啊
		Map<String, Object> map = new HashMap<String, Object>();
		//有些字段不需要,只需要四个字段
		map.put("appId", prePay.getAppid());
		map.put("timeStamp", prePay.getTimeStamp());
		map.put("nonceStr", prePay.getNonce_str());
		map.put("signType", "MD5");
		map.put("package", "prepay_id="+prePay.getPrepay_id());
		String sign = null;
		try {
			sign = Signature.getSignByMD5(map);
		} catch (Exception e) { 
			e.printStackTrace();
		}
		return sign ;
	}
	
	/**
	 * 根据xml信息转换为真正的支付对象
	 * @param xml
	 * @return
	 */
	public static WxPayReturnPrePayId getPaySign(String xml){
		//第一步
		WxPayReturnPrePayId  prePay = XMLUtil.convertXmlStrToObject(WxPayReturnPrePayId.class, xml);
		prePay.setTimeStamp(WxTools.getTimeStamp());
		//第二步
		String paySign = getSignByPrePayId(prePay);
		prePay.setPaySign(paySign);
		return prePay ;
	}
	
	public static void main(String[] args) throws IllegalAccessException, UnsupportedEncodingException {
		/**
		 * 不能使用中文,如果使用中文一定要encode
		 */
		Configure.setKey("KINDNNJLB18Z2J79XACV01LBS3HWY4YD");
		WxPayInfo payInfo = new WxPayInfo();
		payInfo.setAppid("wx60483396471050f8");//嘉湘腾辉appid
		payInfo.setMch_id("1415368202") ; //商户号
		payInfo.setDevice_info("WEB");
		String nonce_str = WxTools.getRandomString(16).toUpperCase();
		System.out.println("随机字符串:"+nonce_str);
		payInfo.setNonce_str(nonce_str);
		payInfo.setBody("JSAPI");
		payInfo.setNotify_url("http://lifenyao.vicp.net/weixin/pay_jxth.jsp");
		payInfo.setOpenid("o2j9nwmZmakpXaUZAI2_pgpEE0E8");
		payInfo.setOut_trade_no("20161221002") ;//商户订单号,需要唯一.
		payInfo.setSpbill_create_ip("118.206.227.140");//用户的IP地址
		payInfo.setTotal_fee("1");//交易金额单位分
		payInfo.setTrade_type("JSAPI") ;
		payInfo.setAttach("liandyao");
		String sign = getSign(payInfo);
		System.out.println("生产的sign数字签名:"+sign);
		payInfo.setSign(sign);
		String xml = XMLUtil.convertToXml(payInfo);
		System.out.println(xml);  
		String str = sendPayInfo(payInfo);
		System.out.println(str);
		
		WxPayReturnPrePayId wp = getPaySign(str);
		
	}
	
	/**
	 * 根据对象得到指定ascii排序的字符串,支付确认的签名算法
	 * @param payInfo
	 * @return
	 * @throws IllegalAccessException
	 * @throws UnsupportedEncodingException 
	 */
	public static String getSign(WxPayInfo payInfo) throws IllegalAccessException, UnsupportedEncodingException{
		String sign = Signature.getSignByMD5(payInfo);
		return sign ;
	}
	
	/**
	 * 得到签名字符串
	 * 传入的参数,之后还是会返回
	 * <pre>
微信开发文档的注意事项

签名用的noncestr和timestamp必须与wx.config中的nonceStr和timestamp相同。
签名用的url必须是调用JS接口页面的完整URL。
出于安全考虑，开发者必须在服务器端实现签名的逻辑。
	 * </pre>
	 * @param jsapi_ticket 传入的参数,之后还是会返回
	 * @param url
	 * @param noncestr
	 * @param timestamp
	 * @return 返回时,会带上sign
	 * @throws DigestException
	 * @throws IllegalAccessException
	 */
	public static JsApiSignInfo getJSAPISign(String jsapi_ticket,String url,String noncestr,String timestamp) throws DigestException, IllegalAccessException{
//		Map<String,Object> map = new HashMap<String, Object>();
//		map.put("noncestr", WxTools.getRandomString(16));
//		map.put("jsapi_ticket", jsapi_ticket);
//		map.put("timestamp",  WxTools.getTimeStamp());
//		map.put("url", url);
		JsApiSignInfo jsApi = new JsApiSignInfo();
		jsApi.setJsapi_ticket(jsapi_ticket);
		jsApi.setNoncestr(noncestr);
		jsApi.setTimestamp(timestamp);
		jsApi.setUrl(url);
		//签名之后,再赋值
		String sign = Signature.getSignBySHA1(jsApi);
		jsApi.setSign(sign);
		return jsApi ;
	}
	
	
	
	public void test1() throws UnsupportedEncodingException{
		String body = new String("");
		//body = new String(body.getBytes("ISO-8859-1"),"UTF-8");
		 String str = "appid=wx60483396471050f8&attach=jxth&body=能力风暴机器人-测试订单&device_info=WEB&mch_id=1415368202&nonce_str=4XNZDBATUCG0EMK7&notify_url=http://lifenyao.vicp.net/wexin/pages/payBuy.jsp&openid=o2j9nwmZmakpXaUZAI2_pgpEE0E8&out_trade_no=201612242043032&spbill_create_ip=127.0.0.1&total_fee=1&trade_type=JSAPI&key=KINDNNJLB18Z2J79XACV01LBS3HWY4YD";
		 String str1 = "jsapi_ticket=kgt8ON7yVITDhtdwci0qeTLbINpzSMBVoxXNZ0f12wHZpq6xMwWa3Jo71osXd5Z-0FCiVl7zp0T1Vawmxbs7cw&noncestr=74ugzfl0cw21mgje&timestamp=1482563503&url=http://lifenyao.vicp.net/wexin/pages/payBuy.jsp";
		 System.out.println(str);
		 try {
			  
			 String result = MD5.MD5Encode(str).toUpperCase();
			 System.out.println(result);
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		 
		  
	}
	

}
